package com.trendit.print.sdk;


import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

import javax.validation.constraints.NotNull;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * @author zhouhaojie
 */
public class DefaultApiClient implements DaquApiClient {

    private String appId;

    private String appKey;

    private String endpoint;

    public DefaultApiClient(@NotNull String appId, @NotNull String appKey, @NotNull String endpoint) {
        this.appId = appId;
        this.appKey = appKey;
        this.endpoint = endpoint;
    }

    public <T extends DaquResponse> T execute(DaquRequest<T> request) {
        T tRsp;
        try {
            String payload;
            if (request.getBizContent() != null && request.getBizModel() == null) {
                payload = request.getBizContent();
            } else {
                payload = JSON.toJSONString(request.getBizModel());
            }
            HttpPost httpPost = new HttpPost(endpoint + request.getApiMethodURL());
            httpPost.setHeaders(headerArray(request, payload));
            httpPost.setEntity(new StringEntity(payload, StandardCharsets.UTF_8));

            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(5 * 1000)
                    .setConnectionRequestTimeout(5 * 1000)
                    .setSocketTimeout(5 * 1000)
                    .build();

            CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
            HttpResponse httpResponse = httpClient.execute(httpPost);

            DaquParser<T> parser = new ObjectJsonParser<>(request.getResponseClass());
            tRsp = parser.parse(EntityUtils.toString(httpResponse.getEntity()));
        } catch (DaquApiException apiException) {
            throw apiException;
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return tRsp;
    }

    private Header[] headerArray(DaquRequest request, String payload) {
        String requestId = UUID.randomUUID().toString();
        Long requestAt = System.currentTimeMillis() / 1000;

        String signData = requestId + appId + requestAt + appKey + payload;
        String signMd5Str = DigestUtils.md5Hex(signData);

        Header[] headers = new Header[8];
        headers[0] = new BasicHeader("Content-Type", "application/json; charset=utf-8");
        headers[1] = new BasicHeader("X-requestid", requestId);
        headers[2] = new BasicHeader("X-appid", appId);
        headers[3] = new BasicHeader("X-reqtime", requestAt + "");
        headers[4] = new BasicHeader("X-sign", signMd5Str);
        headers[5] = new BasicHeader("X-apiVersion", request.getApiVersion());
        headers[6] = new BasicHeader("X-apiMethod", request.getApiMethodName());
        headers[7] = new BasicHeader("X-notifyURL", request.getApiMethodURL());

        return headers;
    }

}
